﻿using AJWPFAdmin.Core.Enums;
using AJWPFAdmin.Core.ExtensionMethods;
using AJWPFAdmin.Core.GlobalEvents;
using AJWPFAdmin.Core.HardwareSDKS.ADSioReader;
using AJWPFAdmin.Core.Logger;
using AJWPFAdmin.Core.Models;
using AJWPFAdmin.Core.Utils;
using DocumentFormat.OpenXml.Bibliography;
using log4net;
using Masuit.Tools.Reflection;
using Prism.Commands;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AJWPFAdmin.Core.HardwareSDKS.Models
{
    public class SioReaderDevice : DeviceInfo
    {

        private SioBase _sioSDK;
        private RcpBase _rcpBase;

        private string _openCMD = "7CFFFFD700020401A8";
        private string _openResetCMD = "7CFFFFD700020400A9";

        private string _closeCMD = "7CFFFFD700020600A7";
        private string _closeResetCMD = "7CFFFFD700020601A6";

        private string _statusText;
        public string StatusText
        {
            get { return _statusText; }
            set { SetProperty(ref _statusText, value); }
        }

        public override void Open()
        {
            try
            {
                _ctrl.Dispatcher.Invoke(() => SetBusyOrError("加载中..."));

                _sioSDK = new SioNet();
                _rcpBase = new RcpBase();

                _sioSDK.onStatus += OnSioSDKStatusChange;
                _sioSDK.onReceived += OnSioSDKReceived;
                _rcpBase.RxRspParsed += OnSioRCPBaseParsed;

                Logger.Debug($"SIOSDK 开始连接 {IP}:{Port}");

                _sioSDK.Connect(IP, Port);

                Logger.Debug($"SIOSDK 连接成功!");

                _ctrl.Dispatcher.Invoke(() =>
                {
                    _ctrl.Source = CommonUtil.CreateBitmapImageFromStream(CommonUtil.GetImageStreamFromLocalOrHttp(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "images", "device-reader.jpg"), out var errMsg));

                    if (!string.IsNullOrWhiteSpace(errMsg))
                    {
                        Logger.Error($"SIOSDK 加载图片资源失败!:{errMsg}");
                    }

                    DeviceBusyOrError = false;
                });

            }
            catch (Exception e)
            {
                Logger
                .Error($"{DeviceDescription}:高频读头设备打开失败:{e.Message}", e);
                _ctrl.Dispatcher.Invoke(() => SetBusyOrError($"高频读头设备打开失败:{e.Message}"));
            }

        }

        private void OnSioRCPBaseParsed(object sender, ProtocolEventArgs e)
        {
            var protocolPacket = e.Protocol;

            switch (protocolPacket.Code)
            {
                case RcpBase.RCP_MM_READ_C_UII:
                    if (protocolPacket.Type == 2 || protocolPacket.Type == 5)
                    {
                        int pcepclen = ((protocolPacket.Payload[1] >> 3) + 1) * 2;
                        int datalen = protocolPacket.Length - 2;//去掉天线号去掉rssi
                        var cp = new ADSioTagInfo
                        {
                            TagType = TagType.TYPE_6C,
                            Length = datalen,//去掉天线号去掉RSSI
                            Antenna = protocolPacket.Payload[0],
                            PCData = ADSioTagInfo.GetData(protocolPacket.Payload, 1, 2),
                            EPCData = ADSioTagInfo.GetData(protocolPacket.Payload, 3, pcepclen - 2),
                            Rssi = GetRssi(protocolPacket.Payload[protocolPacket.Length - 1]) + "dBm"
                        };
                        if ((datalen - pcepclen) > 0) cp.DataBytes = ADSioTagInfo.GetData(protocolPacket.Payload, 1 + pcepclen, datalen - pcepclen);

                        Logger.Debug($"高频读头获取到数据:{cp.EPCString}");

                        _ctrl.Dispatcher.Invoke(() =>
                        {
                            CarIdentificationPlateResult = new CarIdentificationResult
                            {
                                CarNo = cp.EPCString
                            };
                            EventAggregator.GetEvent<DeviceNotifyEvent>().Publish(this);
                        });
                    }
                    break;
                default:
                    break;
            }
        }

        private void OnSioSDKReceived(object sender, ReceivedEventArgs e)
        {
            _rcpBase.ReciveBytePkt(e.Data);
        }

        private void OnSioSDKStatusChange(object sender, StatusEventArgs e)
        {
            _ctrl.Dispatcher.Invoke(() =>
            {
                StatusText = ((SioSDKReaderStatus)e.Status).GetDescription();
            });
        }

        private string GetRssi(byte rssi)
        {
            int rssidBm = (sbyte)rssi; // rssidBm is negative && in bytes
            rssidBm -= Convert.ToInt32("-20", 10);
            rssidBm -= Convert.ToInt32("3", 10);
            return rssidBm.ToString();
        }

        private DelegateCommand<bool?> _toggleSwitchCmd;
        public DelegateCommand<bool?> ToggleSwitchCmd =>
            _toggleSwitchCmd ?? (_toggleSwitchCmd = new DelegateCommand<bool?>(ExecuteToggleSwitchCmd, CanExecuteToggleSwitchCmd));

        async void ExecuteToggleSwitchCmd(bool? isOpen)
        {
            var open = isOpen.GetValueOrDefault();
            
            await ToggleGateSwitchCmdAsync(open);

        }

        bool CanExecuteToggleSwitchCmd(bool? isOpen)
        {
            return !DeviceBusyOrError;
        }

        public override void Close()
        {
            _sioSDK?.DisConnect();
            _rcpBase?.Dispose();
        }

        protected override void OnDeviceReceiveCmdEvent(DeviceReceiveCmdEventArgs e)
        {
            switch (e.Type)
            {
                case DeviceReceiveCmdType.开闸:
                    if (e.DeviceId != Id)
                    {
                        return;
                    }
                    Logger?.Info($"收到开闸事件通知,执行开闸:设备id:{e.DeviceId};IP:{IP}");
                    ExecuteOpenGateCmd((DeviceOpenGateCmdParameter)e.Data);
                    break;

                default:
                    break;
            }
        }

        private async void ExecuteOpenGateCmd(DeviceOpenGateCmdParameter data)
        {
            if ((data?.Open).GetValueOrDefault())
            {
                Logger?.Debug($"{IP}-{Type} 执行开闸。");
                await ToggleGateSwitchCmdAsync(true);
            }
        }

        public override async Task<bool> ToggleGateSwitchCmdAsync(bool open)
        {
            using var db = DbServiceBridgeHandle();

            var cfgJson = db.SystemConfigDictionaries
                    .Where(p => p.Key == SystemConfigKey.EntryConfig)
                    .Select(p => p.StringValue).FirstOrDefault();

            var cfg = CommonUtil.TryGetJSONObject<EntryConfig>(cfgJson) ?? new EntryConfig();

            if (DeviceBusyOrError || _sioSDK == null || cfg.DisableGateControl)
            {
                return false;
            }

            var cmd = open ? _openCMD : _closeCMD;

            var action = open ? "开闸" : "关闸";

            var device = $"读头:{IP}";

            Logger.Debug($"{device}{action}:{cmd}");

            _sioSDK.Send(cmd.HexStringToBytes());

            await Task.Delay(500);

            // 延迟之后发送相反命令
            cmd = open ? _openResetCMD : _closeResetCMD;

            action = open ? "关闸" : "开闸";

            Logger.Debug($"{device}{action}:{cmd}");

            _sioSDK.Send(cmd.HexStringToBytes());

            return true;
        }
    }
}
